package Test;

import java.util.Calendar;

import OfficeServer.log_error.AppointmentException;
import OfficeServer.log_error.Log;
import OfficeServer.log_error.UserException;
import OfficeServer.office.AppointmentList;
import OfficeServer.office.Office;
import OfficeServer.report.Appointment;
import OfficeServer.report.Invoice;
import OfficeServer.report.LabWork;
import OfficeServer.report.Prescription;
import OfficeServer.report.Report;
import OfficeServer.report.Symptoms;
import OfficeServer.report.Treatment;
import OfficeServer.report.VitalSigns;
import OfficeServer.users.AccessLevel;
import OfficeServer.users.Patient;
import OfficeServer.users.PersonalInfo;
import OfficeServer.users.UserList;
import junit.framework.TestCase;

/**
 * @author Chris Bayruns This is where our tests for M5 are.
 */
public class M5Test extends TestCase {
    /**
     * @author Chris Bayruns This test checks the ability to log in.
     * @throws UserException
     */
    public void testInit() {
	Log.initLogger();
    }

    public void initAdmin() {

	try {
	    UserList.clear();
	    UserList.addUser("admin", "admin", "admin", "admin1",
		    AccessLevel.ADMIN);
	} catch (UserException e) {
	}
    }

    /**
     * @author Chris Bayruns
     */
    public void testLogin() {
	Office oTest = new Office();
	initAdmin();
	try {
	    oTest.userLogin("admin", "admin1");
	} catch (Exception e) {
	    fail(e.getMessage());
	}
	assertTrue(oTest.isLoggedIn());

	// assertEquals(newPat, oTest.getUser());

	oTest.userLogout();

	assertFalse(oTest.isLoggedIn());
    }

    /**
     * @author Chris Bayruns This test will test the 3 attempt lockout and a
     *         subsequent unlock.
     */
    /**
     * @author Chris Bayruns
     */
    public void testLoginThreeTryFail() {
	Patient newPat = new Patient();
	newPat.resetAttempts();
	UserList.clear();
	UserList.addUser(newPat);
	newPat.setUsername("test");
	newPat.setPassword("test1");
	Office oTest = new Office();

	// Three wrong passwords
	for (int i = 0; i < 3; i++) {
	    try {
		oTest.userLogin("test", "wrongPassword");
	    } catch (UserException e) {
		assertEquals(UserException.REASON.WRONG_PASSWORD, e.getReason());
	    } catch (Exception e) {
		fail("Login lockout fail");
	    }
	}
	// Now for the lockout
	try {
	    oTest.userLogin("test", "wrongPassword");
	} catch (UserException e) {
	    assertEquals(UserException.REASON.ACCOUNT_LOCKED, e.getReason());

	    // assertEquals(UserException.REASON.ACCOUNT_LOCKED, e.getReason());
	} catch (Exception e) {
	    fail("Login lockout fail");
	}

	// Now try with the correct password
	try {
	    oTest.userLogin("test", "test1");
	    assertFalse(oTest.isLoggedIn());
	} catch (UserException e) {
	    assertEquals(UserException.REASON.ACCOUNT_LOCKED, e.getReason());

	    // assertEquals(UserException.REASON.ACCOUNT_LOCKED, e.getReason());
	} catch (Exception e) {
	    fail("Login lockout fail");
	}

	newPat.resetAttempts();

	// Now try with the correct password and the attempts reset
	try {
	    oTest.userLogin("test", "test1");
	    assertTrue(oTest.isLoggedIn());
	} catch (UserException e) {
	    fail("Login unlock fail");
	} catch (Exception e) {
	    fail("Login unlock fail");
	}
    }

    /**
     * @author Chris Bayruns
     */
    public void testPatientCRUD() {
	initAdmin();
	Office oTest = new Office();
	try {
	    // this is for creating the first user
	    oTest.userLogin("admin", "admin1");
	    oTest.addUser("Test2", "Patient", "pat1", "1pass",
		    AccessLevel.PATIENT);
	} catch (Exception e) {
	    fail(e.getMessage());
	}

	// Test Patient Create
	oTest.userLogout();
	try {
	    oTest.userLogin("pat1", "1pass");
	    PersonalInfo pInfo = oTest.getSelfPersonalInfo();

	    assertEquals("Test2", pInfo.getFirstName());
	    assertEquals("Patient", pInfo.getLastName());
	    assertEquals(AccessLevel.PATIENT, pInfo.getAccessLevel());
	} catch (Exception e) {
	    fail(e.getMessage());
	}

	// Test Patient Outside Update and Read
	oTest.userLogout();
	try {
	    oTest.userLogin("admin", "admin1");
	    oTest.userSearch("Test2", "Patient");

	    PersonalInfo pInfo = oTest.getSearchPersonalInfo();
	    pInfo.setAge(25);
	    pInfo.setCellPhone(5551234);
	    pInfo.setEmail("billg@microsoft.com");
	    oTest.setSearchPersonalInfo(pInfo);

	    oTest.userLogout();
	    oTest.userLogin("pat1", "1pass");
	    pInfo = oTest.getSelfPersonalInfo();

	    assertEquals(25, pInfo.getAge());
	    assertEquals(5551234, pInfo.getCellPhone());
	    assertEquals("billg@microsoft.com", pInfo.getEmail());
	    oTest.userLogout();
	} catch (Exception e) {
	    fail(e.getMessage());
	}

	// Test Patient Delete
	oTest.userLogout();
	try {
	    oTest.userLogin("admin", "admin1");
	    oTest.userSearch("Test2", "Patient");

	    oTest.deleteSearchUser();
	    oTest.userLogout();
	} catch (Exception e) {
	    fail(e.getMessage());
	}
	try {
	    oTest.userLogin("pat1", "1pass");
	} catch (UserException e) {
	    assertEquals(UserException.REASON.NO_ACCOUNT, e.getReason());
	}

    }

    /**
     * @author Chris Bayruns
     */
    public void testDoctorCRUD() {
	initAdmin();
	Office oTest = new Office();
	try {
	    // this is for creating the first user
	    oTest.userLogin("admin", "admin1");
	    oTest.addUser("Test3", "Doctor", "doc1", "1pass",
		    AccessLevel.DOCTOR);
	} catch (Exception e) {
	    fail(e.getMessage());
	}

	// Test Patient Create
	oTest.userLogout();
	try {
	    oTest.userLogin("doc1", "1pass");
	    PersonalInfo pInfo = oTest.getSelfPersonalInfo();

	    assertEquals("Test3", pInfo.getFirstName());
	    assertEquals("Doctor", pInfo.getLastName());
	    assertEquals(AccessLevel.DOCTOR, pInfo.getAccessLevel());
	} catch (Exception e) {
	    fail(e.getMessage());
	}

	// Test Patient Outside Update and Read
	oTest.userLogout();
	try {
	    oTest.userLogin("admin", "admin1");
	    oTest.userSearch("Test3", "Doctor");

	    PersonalInfo pInfo = oTest.getSearchPersonalInfo();
	    pInfo.setAge(60);
	    pInfo.setCellPhone(5554321);
	    pInfo.setEmail("umad@yet.com");
	    oTest.setSearchPersonalInfo(pInfo);

	    oTest.userLogout();
	    oTest.userLogin("doc1", "1pass");
	    pInfo = oTest.getSelfPersonalInfo();

	    assertEquals(60, pInfo.getAge());
	    assertEquals(5554321, pInfo.getCellPhone());
	    assertEquals("umad@yet.com", pInfo.getEmail());
	    oTest.userLogout();
	} catch (Exception e) {
	    fail(e.getMessage());
	}

	// Test Patient Delete
	oTest.userLogout();
	try {
	    oTest.userLogin("admin", "admin1");
	    oTest.userSearch("Test3", "Doctor");

	    oTest.deleteSearchUser();
	    oTest.userLogout();
	} catch (Exception e) {
	    fail(e.getMessage());
	}
	try {
	    oTest.userLogin("doc1", "1pass");
	} catch (UserException e) {
	    assertEquals(UserException.REASON.NO_ACCOUNT, e.getReason());
	}

    }

    /**
     * @author Chris Bayruns
     */
    public void testNurseCRUD() {
	initAdmin();
	Office oTest = new Office();
	try {
	    // this is for creating the first user
	    oTest.userLogin("admin", "admin1");
	    oTest.addUser("Test4", "Nurse", "nur1", "1pass", AccessLevel.NURSE);
	} catch (Exception e) {
	    fail(e.getMessage());
	}

	// Test Patient Create
	oTest.userLogout();
	try {
	    oTest.userLogin("nur1", "1pass");
	    PersonalInfo pInfo = oTest.getSelfPersonalInfo();

	    assertEquals("Test4", pInfo.getFirstName());
	    assertEquals("Nurse", pInfo.getLastName());
	    assertEquals(AccessLevel.NURSE, pInfo.getAccessLevel());
	} catch (Exception e) {
	    fail(e.getMessage());
	}

	// Test Patient Outside Update and Read
	oTest.userLogout();
	try {
	    oTest.userLogin("admin", "admin1");
	    oTest.userSearch("Test4", "Nurse");

	    PersonalInfo pInfo = oTest.getSearchPersonalInfo();
	    pInfo.setAge(30);
	    pInfo.setCellPhone(5551111);
	    pInfo.setEmail("dontemailmeplease@nonexistant.org");
	    oTest.setSearchPersonalInfo(pInfo);

	    oTest.userLogout();
	    oTest.userLogin("nur1", "1pass");
	    pInfo = oTest.getSelfPersonalInfo();

	    assertEquals(30, pInfo.getAge());
	    assertEquals(5551111, pInfo.getCellPhone());
	    assertEquals("dontemailmeplease@nonexistant.org", pInfo.getEmail());
	    oTest.userLogout();
	} catch (Exception e) {
	    fail(e.getMessage());
	}

	// Test Patient Delete
	oTest.userLogout();
	try {
	    oTest.userLogin("admin", "admin1");
	    oTest.userSearch("Test4", "Nurse");

	    oTest.deleteSearchUser();
	    oTest.userLogout();
	} catch (Exception e) {
	    fail(e.getMessage());
	}
	try {
	    oTest.userLogin("nur1", "1pass");
	} catch (UserException e) {
	    assertEquals(UserException.REASON.NO_ACCOUNT, e.getReason());
	}
    }

    /**
     * @author Chris Bayruns
     * @throws Exception
     */
    public void testAppointmentCRUD() throws Exception {
	initAdmin();
	Office oTest = new Office();

	oTest.userLogin("admin", "admin1");
	oTest.addUser("Test", "Patient", "pat1", "1pass", AccessLevel.PATIENT);
	oTest.addUser("Test", "Doctor", "doc1", "1pass", AccessLevel.DOCTOR);
	oTest.addUser("Test2", "Doctor2", "doc2", "1pass", AccessLevel.DOCTOR);
	oTest.addUser("Test", "Nurse", "nur1", "1pass", AccessLevel.NURSE);
	oTest.userLogout();
	oTest.userLogin("pat1", "1pass");

	// Check that the calendar correctly updates the avaliability and
	// creating
	assertEquals(true, oTest.selfCheckCalendar(100)[1][0]);
	oTest.addSelfAppointment(0, 100, 1);
	// oTest.addSelfAppointment(0, 100, 2);
	assertEquals(false, oTest.selfCheckCalendar(100)[1][0]);

	// Check the default appointment and reading
	Appointment tempAppt = oTest.getSelfAppointments().get(0);
	assertEquals(0, tempAppt.getDoctorID());
	assertEquals(null, tempAppt.getReport());
	assertEquals(100, tempAppt.getDay());
	assertEquals(1, tempAppt.getTimeSlot());
	assertEquals(false, tempAppt.isConfirmed());

	oTest.userLogout();
	oTest.userLogin("nur1", "1pass");
	oTest.userSearch("Test", "Patient");

	Appointment tempAppt2 = oTest.getWaitingAppointments().get(0);
	assertEquals(0, tempAppt2.getDoctorID());
	assertEquals(null, tempAppt2.getReport());
	assertEquals(100, tempAppt2.getDay());
	assertEquals(1, tempAppt2.getTimeSlot());
	assertEquals(false, tempAppt2.isConfirmed());
	assertEquals(tempAppt.getPatientID(), tempAppt2.getPatientID());
	assertEquals(tempAppt.getApptID(), tempAppt2.getApptID());

	oTest.confirmSearchUserAppointment(tempAppt2);
	assertEquals(true, tempAppt2.isConfirmed());

	Appointment tempAppt3 = oTest.getAppointmentsByDay(100).get(0);
	assertEquals(tempAppt.getApptID(), tempAppt3.getApptID());

	// Testing update here
	tempAppt3.setDay(101);
	tempAppt3.setDoctorID(1);
	tempAppt3.setTimeSlot(3);

	oTest.updateSearchUserAppointment(tempAppt3);
	boolean flag = false;

	try {
	    Appointment notExist = oTest.getAppointmentsByDay(100).get(0);
	} catch (AppointmentException e) {
	    flag = true;
	} catch (IndexOutOfBoundsException e) {
	    flag = true;
	}
	assertFalse(!flag);

	assertEquals(true, oTest.selfCheckCalendar(100)[1][0]);
	assertEquals(false, oTest.selfCheckCalendar(101)[3][1]);

	// Test Deleting here
	oTest.deleteSearchUserAppointment(tempAppt3);
	assertEquals(true, oTest.selfCheckCalendar(100)[1][0]);
	assertEquals(true, oTest.selfCheckCalendar(101)[3][1]);

	try {
	    Appointment notExist = oTest.getSearchUserAppointments().get(0);
	} catch (IndexOutOfBoundsException e) {
	    flag = true;
	}
	assertFalse(!flag);

    }

    /**
     * @author Chris Bayruns
     * @throws Exception
     */
    public void testTreatmentCRUD() throws Exception {
	initAdmin();
	Office oTest = new Office();

	oTest.userLogin("admin", "admin1");
	oTest.addUser("Test", "Nurse", "nur1", "1pass", AccessLevel.NURSE);
	oTest.addUser("Test", "Patient", "pat1", "1pass", AccessLevel.PATIENT);
	oTest.addUser("Test", "Doctor", "doc1", "1pass", AccessLevel.DOCTOR);
	oTest.userLogout();

	// add an appointment
	oTest.userLogin("pat1", "1pass");
	oTest.addSelfAppointment(0, 100, 0);
	oTest.userLogout();

	oTest.userLogin("nur1", "1pass");
	oTest.userSearch("Test", "Patient");
	Appointment tempAppt = oTest.getWaitingAppointments().get(0);
	oTest.confirmSearchUserAppointment(tempAppt);
	tempAppt = oTest.getSearchUserAppointments().get(0);

	Symptoms mySymptoms = new Symptoms(
		"Runny nose, hurting back, caughing.");
	VitalSigns mySigns = new VitalSigns(120, 80, 101.5, 70, 175, 169);
	// Create a report
	Report myReport = new Report(mySymptoms, mySigns, null,
		tempAppt.getDay(), 1337.7, tempAppt.getPatientID(),
		tempAppt.getDoctorID(), null);
	tempAppt.setReport(myReport);
	Invoice invoice = new Invoice(null, null, 0, null);

	Treatment[] treatments = new Treatment[2];
	//myReport.setTreatments(treatments);

	myReport.setInvoice(invoice);

	String[][] costs = new String[1][2];
	costs[0][0] = "Therapy";
	costs[0][1] = "$90";

	Prescription prescription = new Prescription(null, null, 0, null, 0, 0,
		null);
	LabWork lab_work = new LabWork(null, null, 0, null, 0, null, null);

	treatments[0] = prescription;
	treatments[1] = lab_work;

	//myReport.setTreatments(treatments);

	oTest.updateSearchUserAppointment(tempAppt);
	oTest.userLogout();

	// add some treatments

	oTest.userLogin("nur1", "1pass");

	invoice.setDay(03052011);
	invoice.setDoctor("Dr. Jones");
	invoice.setPatient("Kevin Godd");
	invoice.setCosts(costs);

	prescription.setDoctor("Dr. Kevin");
	prescription.setPatient("John Booth");
	prescription.setInstructions("Take two a day");
	prescription.setDueDate(12082011);
	prescription.setCost(234.00);
	prescription.setDrug("Tylenol");
	prescription.setDosage(2);

	lab_work.setNurse("Nurse Cindy");
	lab_work.setCost(100);
	lab_work.setDoctor("Dr. Smith");
	lab_work.setDueDate(12032011);
	lab_work.setPatient("Bill Bob");
	lab_work.setInstructions("Kill the grems");
	lab_work.setType("Blood");

	oTest.updateSearchUserAppointment(tempAppt);
	oTest.userLogout();

	// assertEquals();
	oTest.userLogin("pat1", "1pass");
	tempAppt.getReport().getTreatments();

	assertEquals("Dr. Kevin", prescription.getDoctor());
	assertEquals(234.00, prescription.getCost());
	assertEquals(100.0, lab_work.getCost());
	assertEquals("Dr. Smith", lab_work.getDoctor());
	assertEquals("Nurse Cindy", lab_work.getNurse());
	assertEquals("Blood", lab_work.getType());
	oTest.userLogout();

	// delete some treatments
	oTest.userLogin("nur1", "1pass");
	prescription.setDoctor(null);
	prescription.setPatient(null);
	prescription.setInstructions(null);
	prescription.setDueDate(0);
	prescription.setCost(0);
	prescription.setDrug(null);
	prescription.setDosage(0);

	lab_work.setNurse(null);
	lab_work.setCost(0);
	lab_work.setDoctor(null);
	lab_work.setDueDate(0);
	lab_work.setPatient(null);
	lab_work.setInstructions(null);
	lab_work.setType(null);

	oTest.updateSearchUserAppointment(tempAppt);
	oTest.userLogout();

	// assertEquals
	oTest.userLogin("pat1", "1pass");

	tempAppt.getReport().getTreatments();

	assertEquals(null, prescription.getDoctor());
	assertEquals(0.0, prescription.getCost());
	assertEquals(0, lab_work.getDueDate());
	assertEquals(null, lab_work.getInstructions());
	assertEquals(null, lab_work.getNurse());
	assertEquals(null, lab_work.getType());
	oTest.userLogout();

    }

    /**
     * @author Earle Harrison
     * @throws Exception
     */
    public void testOrdersCRUD() throws Exception {
	initAdmin();
	Office oTest = new Office();

	oTest.userLogin("admin", "admin1");
	oTest.addUser("Test", "Nurse", "nur1", "1pass", AccessLevel.NURSE);
	oTest.addUser("Test", "Patient", "pat1", "1pass", AccessLevel.PATIENT);
	oTest.addUser("Test", "Doctor", "doc1", "1pass", AccessLevel.DOCTOR);
	oTest.userLogout();

	// add an appointment
	oTest.userLogin("pat1", "1pass");
	oTest.addSelfAppointment(0, 99, 0);
	oTest.userLogout();

	oTest.userLogin("nur1", "1pass");
	oTest.userSearch("Test", "Patient");
	Appointment tempAppt = oTest.getWaitingAppointments().get(0);
	// Appointment tempAppt2 = oTest.getSelfAppointments().get(0);
	oTest.confirmSearchUserAppointment(tempAppt);
	tempAppt = oTest.getSearchUserAppointments().get(0);
	Symptoms mySymptoms = new Symptoms(
		"Runny nose, hurting back, caughing.");
	VitalSigns mySigns = new VitalSigns(120, 80, 101.5, 70, 175, 169);
	// Create a report
	Report myReport = new Report(mySymptoms, mySigns, null,
		tempAppt.getDay(), 1337.7, tempAppt.getPatientID(),
		tempAppt.getDoctorID(), null);
	tempAppt.setReport(myReport);
	oTest.userLogout();
	// adding doctors orders
	oTest.userLogin("doc1", "1pass");
	Treatment[] treatments = new Treatment[1];
	//myReport.setTreatments(treatments);

	Prescription prescription = new Prescription("Dr. Kevin", "John Booth",
		12082011, "Take two a day", 234.00, 2, "Tylenol");

	treatments[0] = prescription;
	//myReport.setTreatments(treatments);
	oTest.updateSearchUserAppointment(tempAppt);

	oTest.userLogout();
	// assertEquals
	oTest.userLogin("pat1", "1pass");

	//Treatment[] tempAppt2 = oTest.getSearchUserAppointments().get(0)
	//	.getReport().getTreatments();

	// assertEquals("Dr. Kevin", tempAppt2[0].;
	//assertEquals(234.00, tempAppt2[0].getCost());
	//assertEquals(2, ((Prescription) tempAppt2[0]).getDosage());
	//assertEquals("John Booth", ((Prescription) tempAppt2[0]).getPatient());
	//assertEquals("Take two a day",
	//	((Prescription) tempAppt2[0]).getInstructions());
	//assertEquals("Tylenol", ((Prescription) tempAppt2[0]).getDrug());
	oTest.userLogout();

	// deletes orders
	oTest.userLogin("doc1", "1pass");

	prescription.setDoctor(null);
	prescription.setPatient(null);
	prescription.setInstructions(null);
	prescription.setDueDate(0);
	prescription.setCost(0);
	prescription.setDrug(null);
	prescription.setDosage(0);

	oTest.updateSearchUserAppointment(tempAppt);
	oTest.userLogout();

	// assertEquals
	oTest.userLogin("pat1", "1pass");
	//assertEquals(null, ((Prescription) tempAppt2[0]).getDoctor());
	//assertEquals(0.0, ((Prescription) tempAppt2[0]).getCost());
	//assertEquals(0, ((Prescription) tempAppt2[0]).getDosage());
	//assertEquals(null, ((Prescription) tempAppt2[0]).getPatient());
	//assertEquals(null, ((Prescription) tempAppt2[0]).getInstructions());
	//assertEquals(null, ((Prescription) tempAppt2[0]).getDrug());
	oTest.userLogout();

    }

    public void testSystemSaveandLoad() throws Exception {
	Office oTest = new Office();
	initAdmin();
	oTest.userLogin("admin", "admin1");
	oTest.addUser("Test", "Patient", "pat1", "1pass", AccessLevel.PATIENT);
	oTest.addUser("Test", "Doctor", "doc1", "1pass", AccessLevel.DOCTOR);
	oTest.addUser("Test2", "Doctor2", "doc2", "1pass", AccessLevel.DOCTOR);
	oTest.addUser("Test", "Nurse", "nur1", "1pass", AccessLevel.NURSE);
	oTest.userLogout();
	oTest.userLogin("pat1", "1pass");
	oTest.addSelfAppointment(0, 100, 1);
	Appointment tempAppt = oTest.getSelfAppointments().get(0);
	oTest.userLogout();
	oTest.userLogin("nur1", "1pass");
	oTest.userSearch("Test", "Patient");
	Appointment tempAppt2 = oTest.getWaitingAppointments().get(0);
	oTest.confirmSearchUserAppointment(tempAppt2);
	Appointment tempAppt3 = oTest.getAppointmentsByDay(100).get(0);
	oTest.userLogout();
	// now save system...
	oTest.save();
	// now clear office lists...
	// appointments...
	UserList.clear();
	AppointmentList.clear();
	OfficeServer.office.Calendar.clear();
	oTest.load();
	oTest.userLogin("pat1", "1pass");
	Appointment tempAppt4 = oTest.getSelfAppointments().get(0);
	assertEquals(0, tempAppt4.getDoctorID());
	assertEquals(null, tempAppt4.getReport());
	assertEquals(100, tempAppt4.getDay());
	assertEquals(1, tempAppt4.getTimeSlot());
	assertEquals(false, tempAppt4.isConfirmed());
    }

}
